From 4f187f2e3424ca0f09bc512496e1a4f76771a272 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 20 Mar 2025 08:17:16 +0100 Subject: [PATCH 1/2] Merging upstream version 4.2.0. Signed-off-by: Daniel Baumann --- .github/workflows/languages.yaml | 2 +- .github/workflows/main.yml | 4 +- .pre-commit-config.yaml | 6 +-- CHANGELOG.md | 13 +++++++ pre_commit/git.py | 2 +- pre_commit/languages/python.py | 34 +++++++++++----- setup.cfg | 2 +- tests/git_test.py | 9 +++++ tests/languages/python_test.py | 67 ++++++++++++++++++++++++++++++++ 9 files changed, 121 insertions(+), 18 deletions(-) diff --git a/.github/workflows/languages.yaml b/.github/workflows/languages.yaml index 61293a0..fccf298 100644 --- a/.github/workflows/languages.yaml +++ b/.github/workflows/languages.yaml @@ -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 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2355b66..7fda646 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a23da2..b216fbd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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] diff --git a/CHANGELOG.md b/CHANGELOG.md index 408afe6..b63f443 100644 --- a/CHANGELOG.md +++ b/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 ================== diff --git a/pre_commit/git.py b/pre_commit/git.py index 19aac38..2f424f8 100644 --- a/pre_commit/git.py +++ b/pre_commit/git.py @@ -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) diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py index 0c4bb62..88ececc 100644 --- a/pre_commit/languages/python.py +++ b/pre_commit/languages/python.py @@ -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,18 +107,25 @@ 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]}' - if find_executable(exe): - return exe + # attempt the likely implementation exe + for potential in (v_minor, v_major): + exe = f'{_impl_exe_name()}{potential}' + if find_executable(exe): + return exe - if _find_by_py_launcher(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 # We tried! return C.DEFAULT diff --git a/setup.cfg b/setup.cfg index 60d9764..af34452 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/tests/git_test.py b/tests/git_test.py index 93f5a1c..02b6ce3 100644 --- a/tests/git_test.py +++ b/tests/git_test.py @@ -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' diff --git a/tests/languages/python_test.py b/tests/languages/python_test.py index ab26e14..565525a 100644 --- a/tests/languages/python_test.py +++ b/tests/languages/python_test.py @@ -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 From 7622bf464d13f8f8aec999df0fc18ad179992922 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 20 Mar 2025 08:17:40 +0100 Subject: [PATCH 2/2] Releasing debian version 4.2.0-1. Signed-off-by: Daniel Baumann --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 9a50475..2502d57 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +pre-commit (4.2.0-1) sid; urgency=medium + + * Merging upstream version 4.2.0. + + -- Daniel Baumann Thu, 20 Mar 2025 08:17:36 +0100 + pre-commit (4.1.0-3) sid; urgency=medium * Updating to standards version 4.7.1.