Skip to content

Commit ead906a

Browse files
committed
Compute win32 python2 length according to encoded size
1 parent 3d573d8 commit ead906a

2 files changed

Lines changed: 42 additions & 24 deletions

File tree

pre_commit/xargs.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import sys
55

6+
import six
7+
68
from pre_commit import parse_shebang
79
from pre_commit.util import cmd_output
810

@@ -19,9 +21,13 @@ def _command_length(*cmd):
1921
# win32 uses the amount of characters, more details at:
2022
# https://github.com/pre-commit/pre-commit/pull/839
2123
if sys.platform == 'win32':
22-
return len(full_cmd.encode('utf-16le')) // 2
23-
24-
return len(full_cmd.encode(sys.getfilesystemencoding()))
24+
# the python2.x apis require bytes, we encode as UTF-8
25+
if six.PY2:
26+
return len(full_cmd.encode('utf-8'))
27+
else:
28+
return len(full_cmd.encode('utf-16le')) // 2
29+
else:
30+
return len(full_cmd.encode(sys.getfilesystemencoding()))
2531

2632

2733
class ArgumentTooLongError(RuntimeError):

tests/xargs_test.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,36 @@
22
from __future__ import absolute_import
33
from __future__ import unicode_literals
44

5+
import sys
6+
57
import mock
68
import pytest
9+
import six
710

811
from pre_commit import xargs
912

1013

1114
@pytest.fixture
12-
def sys_win32_mock():
13-
return mock.Mock(
14-
platform='win32',
15-
getfilesystemencoding=mock.Mock(return_value='utf-8'),
16-
)
15+
def win32_py2_mock():
16+
with mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8'):
17+
with mock.patch.object(sys, 'platform', 'win32'):
18+
with mock.patch.object(six, 'PY2', True):
19+
yield
1720

1821

1922
@pytest.fixture
20-
def sys_linux_mock():
21-
return mock.Mock(
22-
platform='linux',
23-
getfilesystemencoding=mock.Mock(return_value='utf-8'),
24-
)
23+
def win32_py3_mock():
24+
with mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8'):
25+
with mock.patch.object(sys, 'platform', 'win32'):
26+
with mock.patch.object(six, 'PY2', False):
27+
yield
28+
29+
30+
@pytest.fixture
31+
def linux_mock():
32+
with mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8'):
33+
with mock.patch.object(sys, 'platform', 'linux'):
34+
yield
2535

2636

2737
def test_partition_trivial():
@@ -53,31 +63,33 @@ def test_partition_limits():
5363
)
5464

5565

56-
def test_partition_limit_win32(sys_win32_mock):
66+
def test_partition_limit_win32_py3(win32_py3_mock):
5767
cmd = ('ninechars',)
5868
# counted as half because of utf-16 encode
5969
varargs = ('😑' * 5,)
60-
with mock.patch('pre_commit.xargs.sys', sys_win32_mock):
61-
ret = xargs.partition(cmd, varargs, _max_length=20)
70+
ret = xargs.partition(cmd, varargs, _max_length=20)
71+
assert ret == (cmd + varargs,)
72+
6273

74+
def test_partition_limit_win32_py2(win32_py2_mock):
75+
cmd = ('ninechars',)
76+
varargs = ('😑' * 5,) # 4 bytes * 5
77+
ret = xargs.partition(cmd, varargs, _max_length=30)
6378
assert ret == (cmd + varargs,)
6479

6580

66-
def test_partition_limit_linux(sys_linux_mock):
81+
def test_partition_limit_linux(linux_mock):
6782
cmd = ('ninechars',)
6883
varargs = ('😑' * 5,)
69-
with mock.patch('pre_commit.xargs.sys', sys_linux_mock):
70-
ret = xargs.partition(cmd, varargs, _max_length=30)
71-
84+
ret = xargs.partition(cmd, varargs, _max_length=30)
7285
assert ret == (cmd + varargs,)
7386

7487

75-
def test_argument_too_long_with_large_unicode(sys_linux_mock):
88+
def test_argument_too_long_with_large_unicode(linux_mock):
7689
cmd = ('ninechars',)
7790
varargs = ('😑' * 10,) # 4 bytes * 10
78-
with mock.patch('pre_commit.xargs.sys', sys_linux_mock):
79-
with pytest.raises(xargs.ArgumentTooLongError):
80-
xargs.partition(cmd, varargs, _max_length=20)
91+
with pytest.raises(xargs.ArgumentTooLongError):
92+
xargs.partition(cmd, varargs, _max_length=20)
8193

8294

8395
def test_argument_too_long():

0 commit comments

Comments
 (0)