Replace our implementation of shebang parsing with identify's

This commit is contained in:
Anthony Sottile 2017-07-01 20:12:47 -07:00
parent a58d99ac40
commit f956f421be
2 changed files with 4 additions and 57 deletions

View file

@ -1,13 +1,9 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import unicode_literals from __future__ import unicode_literals
import io
import os.path import os.path
import shlex
import string
from identify.identify import parse_shebang_from_file
printable = frozenset(string.printable)
class ExecutableNotFoundError(OSError): class ExecutableNotFoundError(OSError):
@ -15,34 +11,11 @@ class ExecutableNotFoundError(OSError):
return (1, self.args[0].encode('UTF-8'), b'') return (1, self.args[0].encode('UTF-8'), b'')
def parse_bytesio(bytesio):
"""Parse the shebang from a file opened for reading binary."""
if bytesio.read(2) != b'#!':
return ()
first_line = bytesio.readline()
try:
first_line = first_line.decode('US-ASCII')
except UnicodeDecodeError:
return ()
# Require only printable ascii
for c in first_line:
if c not in printable:
return ()
cmd = tuple(shlex.split(first_line))
if cmd[0] == '/usr/bin/env':
cmd = cmd[1:]
return cmd
def parse_filename(filename): def parse_filename(filename):
"""Parse the shebang given a filename.""" if not os.path.exists(filename):
if not os.path.exists(filename) or not os.access(filename, os.X_OK):
return () return ()
else:
with io.open(filename, 'rb') as f: return parse_shebang_from_file(filename)
return parse_bytesio(f)
def find_executable(exe, _environ=None): def find_executable(exe, _environ=None):

View file

@ -15,36 +15,10 @@ from pre_commit.envcontext import Var
from pre_commit.util import make_executable from pre_commit.util import make_executable
@pytest.mark.parametrize(
('s', 'expected'),
(
(b'', ()),
(b'#!/usr/bin/python', ('/usr/bin/python',)),
(b'#!/usr/bin/env python', ('python',)),
(b'#! /usr/bin/python', ('/usr/bin/python',)),
(b'#!/usr/bin/foo python', ('/usr/bin/foo', 'python')),
(b'\xf9\x93\x01\x42\xcd', ()),
(b'#!\xf9\x93\x01\x42\xcd', ()),
(b'#!\x00\x00\x00\x00', ()),
),
)
def test_parse_bytesio(s, expected):
assert parse_shebang.parse_bytesio(io.BytesIO(s)) == expected
def test_file_doesnt_exist(): def test_file_doesnt_exist():
assert parse_shebang.parse_filename('herp derp derp') == () assert parse_shebang.parse_filename('herp derp derp') == ()
@pytest.mark.xfail(
sys.platform == 'win32', reason='Windows says everything is X_OK',
)
def test_file_not_executable(tmpdir):
x = tmpdir.join('f')
x.write_text('#!/usr/bin/env python', encoding='UTF-8')
assert parse_shebang.parse_filename(x.strpath) == ()
def test_simple_case(tmpdir): def test_simple_case(tmpdir):
x = tmpdir.join('f') x = tmpdir.join('f')
x.write_text('#!/usr/bin/env python', encoding='UTF-8') x.write_text('#!/usr/bin/env python', encoding='UTF-8')