From 4f8a9580aa71ec47e7f55d41a4131a88fe0cd862 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 10 Jan 2019 14:26:55 -0800 Subject: [PATCH] Be more timid about choosing a shebang --- pre_commit/commands/install_uninstall.py | 18 ++++++++++++++---- tests/commands/install_uninstall_test.py | 21 +++++++++++---------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py index 4ff2a413..a6d501ab 100644 --- a/pre_commit/commands/install_uninstall.py +++ b/pre_commit/commands/install_uninstall.py @@ -2,15 +2,14 @@ from __future__ import print_function from __future__ import unicode_literals import io +import itertools import logging import os.path import sys -import pre_commit.constants as C from pre_commit import git from pre_commit import output from pre_commit.clientlib import load_config -from pre_commit.languages import python from pre_commit.repository import all_hooks from pre_commit.repository import install_hook_envs from pre_commit.util import cmd_output @@ -51,8 +50,19 @@ def shebang(): if sys.platform == 'win32': py = 'python' else: - py = python.get_default_version() - if py == C.DEFAULT: + # Homebrew/homebrew-core#35825: be more timid about appropriate `PATH` + path_choices = [p for p in os.defpath.split(os.pathsep) if p] + exe_choices = [ + 'python{}'.format('.'.join( + str(v) for v in sys.version_info[:i] + )) + for i in range(3) + ] + for path, exe in itertools.product(path_choices, exe_choices): + if os.path.exists(os.path.join(path, exe)): + py = exe + break + else: py = 'python' return '#!/usr/bin/env {}'.format(py) diff --git a/tests/commands/install_uninstall_test.py b/tests/commands/install_uninstall_test.py index 608fe385..c19aaa44 100644 --- a/tests/commands/install_uninstall_test.py +++ b/tests/commands/install_uninstall_test.py @@ -18,7 +18,6 @@ from pre_commit.commands.install_uninstall import is_our_script from pre_commit.commands.install_uninstall import PRIOR_HASHES from pre_commit.commands.install_uninstall import shebang from pre_commit.commands.install_uninstall import uninstall -from pre_commit.languages import python from pre_commit.util import cmd_output from pre_commit.util import make_executable from pre_commit.util import mkdirp @@ -51,19 +50,21 @@ def test_shebang_windows(): assert shebang() == '#!/usr/bin/env python' -def test_shebang_otherwise(): +def test_shebang_posix_not_on_path(): with mock.patch.object(sys, 'platform', 'posix'): - assert C.DEFAULT not in shebang() - - -def test_shebang_returns_default(): - with mock.patch.object(sys, 'platform', 'posix'): - with mock.patch.object( - python, 'get_default_version', return_value=C.DEFAULT, - ): + with mock.patch.object(os, 'defpath', ''): assert shebang() == '#!/usr/bin/env python' +def test_shebang_posix_on_path(tmpdir): + tmpdir.join('python{}'.format(sys.version_info[0])).ensure() + + with mock.patch.object(sys, 'platform', 'posix'): + with mock.patch.object(os, 'defpath', tmpdir.strpath): + expected = '#!/usr/bin/env python{}'.format(sys.version_info[0]) + assert shebang() == expected + + def test_install_pre_commit(in_git_dir, store): assert not install(C.CONFIG_FILE, store) assert os.access(in_git_dir.join('.git/hooks/pre-commit').strpath, os.X_OK)