From c2e4040756e330284ed21480130a0f5d6f6afeea Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Wed, 4 Jul 2018 14:14:29 -0700 Subject: [PATCH] Improve not found error with script paths (`./exe`) --- pre_commit/parse_shebang.py | 19 ++++++++++++------- tests/parse_shebang_test.py | 24 ++++++++++++++++++++---- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/pre_commit/parse_shebang.py b/pre_commit/parse_shebang.py index 33326819..5a2ba72f 100644 --- a/pre_commit/parse_shebang.py +++ b/pre_commit/parse_shebang.py @@ -42,16 +42,21 @@ def find_executable(exe, _environ=None): return None -def normexe(orig_exe): - if os.sep not in orig_exe: - exe = find_executable(orig_exe) +def normexe(orig): + def _error(msg): + raise ExecutableNotFoundError('Executable `{}` {}'.format(orig, msg)) + + if os.sep not in orig and (not os.altsep or os.altsep not in orig): + exe = find_executable(orig) if exe is None: - raise ExecutableNotFoundError( - 'Executable `{}` not found'.format(orig_exe), - ) + _error('not found') return exe + elif not os.access(orig, os.X_OK): + _error('not found') + elif os.path.isdir(orig): + _error('is a directory') else: - return orig_exe + return orig def normalize_cmd(cmd): diff --git a/tests/parse_shebang_test.py b/tests/parse_shebang_test.py index 3f87aea8..bcd6964b 100644 --- a/tests/parse_shebang_test.py +++ b/tests/parse_shebang_test.py @@ -85,6 +85,22 @@ def test_normexe_does_not_exist(): assert excinfo.value.args == ('Executable `i-dont-exist-lol` not found',) +def test_normexe_does_not_exist_sep(): + with pytest.raises(OSError) as excinfo: + parse_shebang.normexe('./i-dont-exist-lol') + assert excinfo.value.args == ('Executable `./i-dont-exist-lol` not found',) + + +def test_normexe_is_a_directory(tmpdir): + with tmpdir.as_cwd(): + tmpdir.join('exe').ensure_dir() + exe = os.path.join('.', 'exe') + with pytest.raises(OSError) as excinfo: + parse_shebang.normexe(exe) + msg, = excinfo.value.args + assert msg == 'Executable `{}` is a directory'.format(exe) + + def test_normexe_already_full_path(): assert parse_shebang.normexe(sys.executable) == sys.executable @@ -107,14 +123,14 @@ def test_normalize_cmd_PATH(): def test_normalize_cmd_shebang(in_tmpdir): - python = distutils.spawn.find_executable('python') - path = write_executable(python.replace(os.sep, '/')) + python = distutils.spawn.find_executable('python').replace(os.sep, '/') + path = write_executable(python) assert parse_shebang.normalize_cmd((path,)) == (python, path) def test_normalize_cmd_PATH_shebang_full_path(in_tmpdir): - python = distutils.spawn.find_executable('python') - path = write_executable(python.replace(os.sep, '/')) + python = distutils.spawn.find_executable('python').replace(os.sep, '/') + path = write_executable(python) with bin_on_path(): ret = parse_shebang.normalize_cmd(('run',)) assert ret == (python, os.path.abspath(path))