Skip to content

Commit 45e3dab

Browse files
committed
Shuffle arguments before running hooks
1 parent 6b6ebe7 commit 45e3dab

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

pre_commit/languages/helpers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22

33
import multiprocessing
44
import os
5+
import random
56
import shlex
67

8+
import six
9+
710
from pre_commit.util import cmd_output
811
from pre_commit.xargs import xargs
912

1013

14+
FIXED_RANDOM_SEED = 1542676186
15+
16+
1117
def run_setup_cmd(prefix, cmd):
1218
cmd_output(*cmd, cwd=prefix.prefix_dir, encoding=None)
1319

@@ -64,5 +70,21 @@ def target_concurrency(hook):
6470
return 1
6571

6672

73+
def _shuffled(seq):
74+
"""Deterministically shuffle identically under both py2 + py3."""
75+
fixed_random = random.Random()
76+
if six.PY2: # pragma: no cover (py2)
77+
fixed_random.seed(FIXED_RANDOM_SEED)
78+
else:
79+
fixed_random.seed(FIXED_RANDOM_SEED, version=1)
80+
81+
seq = list(seq)
82+
random.shuffle(seq, random=fixed_random.random)
83+
return seq
84+
85+
6786
def run_xargs(hook, cmd, file_args):
87+
# Shuffle the files so that they more evenly fill out the xargs partitions,
88+
# but do it deterministically in case a hook cares about ordering.
89+
file_args = _shuffled(file_args)
6890
return xargs(cmd, file_args, target_concurrency=target_concurrency(hook))

tests/languages/helpers_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,7 @@ def test_target_concurrency_cpu_count_not_implemented():
6262
):
6363
with mock.patch.dict(os.environ, {}, clear=True):
6464
assert helpers.target_concurrency({'require_serial': False}) == 1
65+
66+
67+
def test_shuffled_is_deterministic():
68+
assert helpers._shuffled(range(10)) == [3, 7, 8, 2, 4, 6, 5, 1, 0, 9]

0 commit comments

Comments
 (0)